#ifndef CALLER_ONCE_H_
#define CALLER_ONCE_H_

#include <mutex>
#include "Mipi.h"

namespace hiych {

struct CALL_ONCE_VI_VPSS_VO_Create
{
    bool operator()(const VideoInput& vi,const VideoProcSubSys& vpss,const VideoOutput& vo)
    {
        return VI_VPSS_VO_Create(vi, vpss ,vo);
    }
};

struct CALL_ONCE_VI_VPSS_VO_Release
{
    bool operator()(const VideoInput& vi,const VideoProcSubSys& vpss,const VideoOutput& vo)
    {
        return VI_VPSS_VO_Release(vi, vpss ,vo);
    }
};

struct CALL_ONCE_VI_VPSS_VO_Stop
{
    bool operator()(const VideoInput& vi,const VideoProcSubSys& vpss,const VideoOutput& vo)
    {
        return VI_VPSS_VO_Stop(vi, vpss, vo);
    }
};

struct CALL_ONCE_GET_MIPI_Id
{
    int operator()()
    {
        int fd = 0;
        SAMPLE_VO_CONFIG_MIPI(&fd);
        return fd;
    }
};

struct CALL_ONCE_CLOSE_MIPI_Id
{
    bool operator()(int fd)
    {
        return MIPI_Close(fd);
    }
};

template<typename T>
struct Caller
{
    static int GET_MIPI_Id()
    {
        int id = -1;
        std::call_once(
                    flag_id,[&]()mutable{
            id = T()();
        }
        );
        return id;
    }

    static bool VI_VPSS_VO_Relate(const VideoInput& vi,const VideoProcSubSys& vpss,const VideoOutput& vo)
    {
        bool ret = false;

        std::call_once(
                    flag_id,[&]()mutable{
            ret = T()(vi, vpss, vo);
        }
        );

        return ret;
    }

    static bool CLOSE_MIPI_Id(int fd)
    {
        bool ret = false;
        std::call_once(
                    flag_id,[&]()mutable{
            ret = T()(fd);
        }
        );
        return ret;
    }
    
private:
    static std::once_flag flag_id;
};

template<typename T>
std::once_flag Caller<T>::flag_id;

}

#endif